package com.fresher.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.fresher.model.Accountinfo;
import com.fresher.model.Transaction;
import com.fresher.model.User;

/**
 * DAO class for Account entity. This class contains all methods that
 * inserts/updates/deletes account info
 * 
 * @author nvu3
 *
 */
@Repository
public class TransactionDao {

	/**
	 * @return all accounts from Account table
	 */

    @PersistenceContext
    private EntityManager entityManager;
	// get all recent account
    
    @Transactional
	public List<Transaction> getRecentTransaction(String loginId) {

		// Obtains entity manager object


		// Obtains transaction from entity manager


		// -----------Begin transaction-----------

		List<Transaction> TransactionFull = new ArrayList<Transaction>();
		List<Accountinfo> AccountList = null;
		/* try { */


		TypedQuery<User> query = entityManager.createQuery(
				"SELECT c FROM User c Where c.username= :para1", User.class);
		query.setParameter("para1", loginId);

		User user = (User) query.getSingleResult();
		AccountList = (List<Accountinfo>) user.getAccountinfos();
		for (Accountinfo acc : AccountList) {
			TypedQuery<Transaction> query1 = entityManager
					.createQuery(
							"SELECT t FROM Transaction t Where t.accountinfo1.idaccountInfo=:accNum GROUP BY t.accountinfo2.idaccountInfo",
							Transaction.class);
			query1.setParameter("accNum", acc.getIdaccountInfo());
			List<Transaction> Transaction = query1.getResultList();
			for (Transaction transaction2 : Transaction) {
				TransactionFull.add(transaction2);

			}

		}

		// -----------End transaction-----------

		return TransactionFull;

	}

	// get all transaction list
    @Transactional
	public List<Transaction> getTransaction(String loginId) {

		// Obtains entity manager object


		// Obtains transaction from entity manager
		

		// -----------Begin transaction-----------

		List<Transaction> TransactionFull = new ArrayList<Transaction>();
		List<Accountinfo> AccountList = null;
		/* try { */
	

		TypedQuery<User> query = entityManager.createQuery(
				"SELECT c FROM User c Where c.username= :para1", User.class);
		query.setParameter("para1", loginId);

		User user = (User) query.getSingleResult();
		AccountList = (List<Accountinfo>) user.getAccountinfos();
		for (Accountinfo acc : AccountList) {
			TypedQuery<Transaction> query1 = entityManager
					.createQuery(
							"SELECT t FROM Transaction t Where t.accountinfo1.idaccountInfo=:accNum OR t.accountinfo2.idaccountInfo=:accNum",
							Transaction.class);
			query1.setParameter("accNum", acc.getIdaccountInfo());
			List<Transaction> Transaction = query1.getResultList();
			for (Transaction transaction2 : Transaction) {
				TransactionFull.add(transaction2);

			}

		}

		// -----------End transaction-----------

		return TransactionFull;

	}

	// get all send transaction list
    @Transactional
	public List<Transaction> getSendTransaction(String loginId) {

		// Obtains entity manager object


		// Obtains transaction from entity manager
		

		// -----------Begin transaction-----------

		List<Transaction> TransactionFull = new ArrayList<Transaction>();
		List<Accountinfo> AccountList = null;
		


		TypedQuery<User> query = entityManager.createQuery(
				"SELECT c FROM User c Where c.username= :para1", User.class);
		query.setParameter("para1", loginId);

		User user = (User) query.getSingleResult();
		AccountList = (List<Accountinfo>) user.getAccountinfos();
		for (Accountinfo acc : AccountList) {
			TypedQuery<Transaction> query1 = entityManager
					.createQuery(
							"SELECT t FROM Transaction t Where t.accountinfo1.idaccountInfo=:accNum",
							Transaction.class);
			query1.setParameter("accNum", acc.getIdaccountInfo());
			List<Transaction> Transaction = query1.getResultList();
			for (Transaction transaction2 : Transaction) {
				TransactionFull.add(transaction2);

			}

		}

		// -----------End transaction-----------

		return TransactionFull;

	}

	// get all recieve transaction list
    @Transactional
	public List<Transaction> getReceiveTransaction(String loginId) {

		// Obtains entity manager object


		// Obtains transaction from entity manager


		// -----------Begin transaction-----------

		List<Transaction> TransactionFull = new ArrayList<Transaction>();
		List<Accountinfo> AccountList = null;


		TypedQuery<User> query = entityManager.createQuery(
				"SELECT c FROM User c Where c.username= :para1", User.class);
		query.setParameter("para1", loginId);

		User user = (User) query.getSingleResult();
		AccountList = (List<Accountinfo>) user.getAccountinfos();
		for (Accountinfo acc : AccountList) {
			TypedQuery<Transaction> query1 = entityManager
					.createQuery(
							"SELECT t FROM Transaction t Where t.accountinfo2.idaccountInfo=:accNum",
							Transaction.class);
			query1.setParameter("accNum", acc.getIdaccountInfo());
			List<Transaction> Transaction = query1.getResultList();
			for (Transaction transaction2 : Transaction) {
				TransactionFull.add(transaction2);

			}

		}

		// -----------End transaction-----------

		return TransactionFull;

	}

	// search transaction
	// get all account list
    @Transactional
	public List<Transaction> searchTransaction(String loginId, Date startDate,
			Date endDate, String transType) {

		// Obtains entity manager object

		// Obtains transaction from entity manager


		// -----------Begin transaction-----------

		List<Transaction> TransactionFull = new ArrayList<Transaction>();
		List<Accountinfo> AccountList = null;


		TypedQuery<User> query = entityManager.createQuery(
				"SELECT c FROM User c Where c.username= :para1", User.class);
		query.setParameter("para1", loginId);

		User user = (User) query.getSingleResult();
		AccountList = (List<Accountinfo>) user.getAccountinfos();
		for (Accountinfo acc : AccountList) {

			if (transType.equals("all")) {
				TypedQuery<Transaction> query1 = entityManager
						.createQuery(
								"SELECT t FROM Transaction t Where( t.accountinfo1.idaccountInfo=:accNum OR t.accountinfo2.idaccountInfo=:accNum) and (date(t.date) between :startdate and :enddate) ",
								Transaction.class);
				query1.setParameter("accNum", acc.getIdaccountInfo());
				query1.setParameter("startdate", startDate);
				query1.setParameter("enddate", endDate);
				List<Transaction> Transaction = query1.getResultList();
				for (Transaction transaction2 : Transaction) {
					TransactionFull.add(transaction2);

				}
			}
			else if (transType.equals("sent")) {
				TypedQuery<Transaction> query1 = entityManager
						.createQuery(
								"SELECT t FROM Transaction t Where( t.accountinfo1.idaccountInfo=:accNum ) and (date(t.date) between :startdate and :enddate) ",
								Transaction.class);
				query1.setParameter("accNum", acc.getIdaccountInfo());
				query1.setParameter("startdate", startDate);
				query1.setParameter("enddate", endDate);
				List<Transaction> Transaction = query1.getResultList();
				for (Transaction transaction2 : Transaction) {
					TransactionFull.add(transaction2);

				}
			}
			else if (transType.equals("received")) {
				TypedQuery<Transaction> query1 = entityManager
						.createQuery(
								"SELECT t FROM Transaction t Where( t.accountinfo2.idaccountInfo=:accNum ) and (date(t.date) between :startdate and :enddate) ",
								Transaction.class);
				query1.setParameter("accNum", acc.getIdaccountInfo());
				query1.setParameter("startdate", startDate);
				query1.setParameter("enddate", endDate);
				List<Transaction> Transaction = query1.getResultList();
				for (Transaction transaction2 : Transaction) {
					TransactionFull.add(transaction2);

				}
			}

		}

		// -----------End transaction-----------

		return TransactionFull;

	}

	// add transaction
    @Transactional
	public boolean addTransaction(Transaction Transaction, int sourceAccountID,
			int targetAccountID) {
		// Obtains entity manager object
		// Obtains transaction from entity manager
			// set accountid and account id to
			// set account id from and to for transaction
			Accountinfo Accountinfo = entityManager.getReference(
					Accountinfo.class, sourceAccountID);
			Accountinfo Accountinfo2 = entityManager.getReference(
					Accountinfo.class, targetAccountID);
			Transaction.setAccountinfo1(Accountinfo);
			Transaction.setAccountinfo2(Accountinfo2);

			// update balance
			// call updateAccountTo to subtract amount from account from
			updateAccountFrom(Transaction, sourceAccountID);
			// call updateAccountFrom to update new balance to account to
			updateAccountTo(Transaction, targetAccountID);

			// add new tran
			// Insert a row to Account table
			entityManager.persist(Transaction);

		// -----------End transaction-----------
		return true;
	}

	// update balance for account
    @Transactional
	public void updateAccountFrom(Transaction Transaction, int accountid) {


			Accountinfo accountfrom = entityManager.find(Accountinfo.class,
					accountid);
			if (accountfrom == null) {
				throw new IllegalArgumentException("Unknown Employee id");
			}
			accountfrom.setBalance(Transaction.getAfterBalance());
			// update
			entityManager.merge(accountfrom);

	}

	// update balance for account
	public void updateAccountTo(Transaction Transaction, int accountidto) {


			Accountinfo accountto = entityManager.find(Accountinfo.class,
					accountidto);
			if (accountto == null) {
				throw new IllegalArgumentException("Unknown Employee id");
			}

			accountto.setBalance(Transaction.getAmount()
					+ accountto.getBalance());
			// update
			entityManager.merge(accountto);

	}

}
